﻿Public Class WeeklyScheduleData
    Class TimeSlot
        Property StartTime As TimeSpan
        Property EndTime As TimeSpan
        Property Day As DayOfWeek
        Property Schedules As New List(Of EmployeeSchedule)
    End Class
    Class EmployeeSchedule
        Property Employee As Employee
        Property StartTime As Date
        Property EndTime As Date
        Property ScheduleType
    End Class
    Property Slots As New List(Of TimeSlot)
    Private Employees As EmployeeList
    Private EmployeeTypes() As String
    Private ScheduleTypes As String()
    Private weekdate As Date
    Public Sub New(WeekDate As Date?, ByVal EmployeeTypes As String(), ByVal StartTime As TimeSpan, EndTime As TimeSpan, TimeSlotSize As TimeSpan, employees As EmployeeList, ScheduleTypes As String())
        Me.Employees = employees
        Me.EmployeeTypes = EmployeeTypes
        Me.ScheduleTypes = ScheduleTypes
        If Not WeekDate.HasValue Then WeekDate = GetLastDay(DayOfWeek.Sunday, Now.Date)
        Me.weekdate = WeekDate
        For x = 0 To 6

            Dim current As TimeSpan = StartTime
            While current < EndTime
                Dim slot As New TimeSlot
                With slot
                    .StartTime = current
                    If current = StartTime Then
                        .EndTime = current.Add(TimeSpan.FromMinutes(60 - current.Minutes))
                        If current.Hours = .EndTime.Hours Then .EndTime = current.Add(TimeSpan.FromHours(1))
                    Else
                        .EndTime = current.Add(TimeSlotSize)
                    End If

                    .Day = x
                    .Schedules = GetEmployeesInTimeRange(slot)
                End With
                Slots.Add(slot)
                current = slot.EndTime
            End While

        Next
        Dim tmpq = From slt In Slots Group slt By slt.Day Into SlotDays = Group
                    Where SlotDays.Sum(Function(s)
                                           Return s.Schedules.Count
                                       End Function) = 0 Select SlotDays


        Dim rmSlot = tmpq.SelectMany(Function(ts, index)
                                         Return ts
                                     End Function)




        For Each slot In rmSlot
            Slots.Remove(slot)

        Next

    End Sub
    Private Function GetEmployeesInTimeRange(Slot As TimeSlot) As List(Of EmployeeSchedule)
        Dim emps As New List(Of EmployeeSchedule)
        Dim cantFilterScheduleTypes As Boolean = ScheduleTypes Is Nothing OrElse ScheduleTypes.Length = 0
        For Each emp In Me.Employees
            Dim tmpemp = emp
            Dim empContained = From sch In emps Where sch.Employee Is tmpemp


            If empContained.FirstOrDefault IsNot Nothing OrElse (Me.EmployeeTypes.Count > 0 AndAlso Not Me.EmployeeTypes.Contains(emp.EmployeeType)) Then Continue For
            For x As Integer = 0 To emp.Days(Slot.Day).StartTimes.Length - 1
                Dim startT As DateTime = emp.Days(Slot.Day).StartTimes(x)
                Dim endT As DateTime = emp.Days(Slot.Day).EndTimes(x)
                Dim tiWeek As New DevExpress.XtraScheduler.TimeInterval(weekdate, GetNextDay(DayOfWeek.Saturday, weekdate).AddHours(23).AddMinutes(59))
                Dim tiWork As New DevExpress.XtraScheduler.TimeInterval(startT, endT)
                If tiWeek.IntersectsWith(tiWork) Then
                    'Starts in slot
                    'starts before slot and ends in slot
                    'starts before slot and ends after slot

                    If (startT.TimeOfDay >= Slot.StartTime AndAlso startT.TimeOfDay <= Slot.EndTime.Subtract(TimeSpan.FromSeconds(1))) OrElse
                        (startT.TimeOfDay < Slot.StartTime AndAlso endT.TimeOfDay <= Slot.EndTime AndAlso endT.TimeOfDay >= Slot.StartTime.Add(TimeSpan.FromSeconds(1))) OrElse
                        (startT.TimeOfDay < Slot.StartTime AndAlso endT.TimeOfDay > Slot.EndTime) Then

                        If cantFilterScheduleTypes OrElse Me.ScheduleTypes.Contains(emp.Days(Slot.Day).ScheduleEmployeeTypes(x)) Then
                            emps.Add(New EmployeeSchedule With {.Employee = emp, .StartTime = startT, .EndTime = endT, .ScheduleType = emp.Days(Slot.Day).ScheduleEmployeeTypes(x)})

                            ' Exit For
                        End If
                    End If
                End If

            Next
        Next

        Return emps
    End Function
    Public Function SlotDays() As Integer
        Return (From slt In Slots Group By slt.Day Into SlotsDay = Group
                       Select SlotsDay).Count()
    End Function
    Public Function SlotsPerDay() As Integer
        Dim tmpqry = From slt In Slots Group By slt.Day Into SlotsDay = Group
        Where Day = SlotsDay.First.Day
               Select New With {Key .Day = Day, .Slots = SlotsDay}

        Return tmpqry.First.Slots.Count

    End Function

End Class
